package com.snda.sc.store;

import java.io.File;
import java.nio.file.Files;
import java.util.Set;

import javax.annotation.PreDestroy;

import org.springframework.stereotype.Component;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.snda.sc.config.Configurable;
import com.snda.sc.exception.ConfigureException;
import com.snda.sc.utils.Charsets;
import com.snda.sc.utils.CommonUtils;
import com.snda.sc.utils.Logs;

@Component("redisStore")
public class RedisStore implements IRedisStore, Configurable {

	public static final String REDISPOOL_CONFIG_FILENAME = "store.json";

	private volatile JedisPool pool;
	private volatile int codeExpire = 2 * 60 * 60;
	private volatile int hpsExpire = 6 * 60 * 60;

	@Override
	public void configure(File confFile) throws Exception {
		JSONObject conf = JSON.parseObject(new String(Files.readAllBytes(confFile.toPath()), Charsets.UTF_8));
		JSONObject redisConf = conf.getJSONObject("redis");
		if (redisConf == null) throw new ConfigureException("Redis config node is undefined in store.json.");
		pool = createPool(redisConf);
		Logs.logSysInfo("Redis connected, use config: {}", redisConf);
	}

	@Override
	public Set<String> getConfigFileNames() {
		return CommonUtils.initSet(REDISPOOL_CONFIG_FILENAME);
	}

	@Override
	public boolean watchModify() {
		return false;
	}

	@Override
	public Scope getScope() {
		return Scope.GLOBAL;
	}

	@Override
	public Jedis getConnection() {
		return pool.getResource();
	}

	@Override
	public void returnConnection(Jedis jedis) {
		pool.returnResource(jedis);
	}

	@Override
	public boolean exists(String key) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.exists(key);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public String get(String key) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.get(key);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.set(key, value);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public String setCodeExpire(String key, String value) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.setex(key, codeExpire, value);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public String setHpsExpire(String key, String value) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.setex(key, hpsExpire, value);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public String setExpire(String key, int seconds, String value) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.setex(key, seconds, value);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public long ttl(String key) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.ttl(key);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public long del(String key) {
		Jedis jedis = pool.getResource();
		try {
			return jedis.del(key);
		} finally {
			pool.returnResource(jedis);
		}
	}

	@Override
	public long size() {
		Jedis jedis = pool.getResource();
		try {
			return jedis.dbSize();
		} finally {
			pool.returnResource(jedis);
		}
	}

	@PreDestroy
	public void destroy() {
		if (pool != null) pool.destroy();
	}

	private JedisPool createPool(JSONObject jsonConfig) {
		String host = jsonConfig.getString("host");
		int port = jsonConfig.getIntValue("port");

		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxActive(jsonConfig.getIntValue("maxActive"));
		config.setMaxIdle(jsonConfig.getIntValue("maxIdle"));
		config.setMaxWait(jsonConfig.getInteger("maxWait"));

		config.setTestOnBorrow(jsonConfig.getBoolean("testBorrow"));
		config.setTestOnReturn(jsonConfig.getBoolean("testReturn"));

		codeExpire = jsonConfig.getIntValue("codeExpire") * 60;
		hpsExpire = jsonConfig.getIntValue("hpsExpire") * 60;

		return new JedisPool(config, host, port);
	}
}
